package com.game.sample;

import java.io.File;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.game.monitor.FileLoader;
import com.game.monitor.FileMonitor;
import com.game.sample.helper.SampleReflectHelper;


import com.game.utils.ExcelUtil;
import com.game.utils.FileHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(1)
public class SampleLoader implements ApplicationRunner, FileLoader {
    Logger log = LoggerFactory.getLogger(getClass());

    private SampleConfig sampleConfig;

    @Autowired
    private FileMonitor monitor;

    @Autowired
    public SampleLoader(SampleConfig sampleConfig) {
        this.sampleConfig = sampleConfig;
    }

    public void run(ApplicationArguments args) throws Exception {
        this.log.info("begin to load sample files...");
        String samplePath = this.sampleConfig.samplePath;
        if (samplePath == null) {
            return;
        }
        File file = new File(samplePath);
        loadSample(file);
        this.monitor.addDirectoryObserver(samplePath, this);
    }

    public void loadSample(File file) {
        if (file == null || !file.exists() || file.isHidden() || file
                .getName().endsWith(".svn") || file
                .getName().endsWith(".bak"))
            return;
        if (file.isDirectory()) {
            Arrays.<File>asList(file.listFiles()).forEach(f -> loadSample(f));
            return;
        }
        String fileName = file.getName();
        if (fileName.endsWith(".csv")) {
//            loadSampleByCsv(file);
        } else if (fileName.endsWith(".xlsx")) {
            loadSampleByExcel(file);
        }
    }

//    public void loadSampleByCsv(File file) {
//        List<String[]> values = FileHelper.readCsvFile(file);
//        if (values == null || values.size() < 4) {
//            return;
//        }
//        String parent = file.getParent().replace(File.separator, ".");
//        String fileName = file.getName();
//        String className = fileName.substring(0, fileName.indexOf('.'));
//        values.remove(0);
//        String[] names = values.remove(0);
//        values.remove(0);
//        String clazzName = this.sampleConfig.samplePackage + "." + parent + "." + className;
//        try {
//            Class<Sample> clazz = (Class)Class.forName(clazzName);
//            List<Sample> samples = SampleReflectHelper.resolveSample(clazz, names, values);
//            Field field = clazz.getField("factory");
//            SampleFactory<Sample> factory = (SampleFactory)field.get(null);
//            factory.addSamples(samples);
//        } catch (Exception e) {
//            this.log.warn("parse file error, file is {}", fileName, e);
//        }
//    }

    public void loadSampleByExcel(File file) {
        Map<String, List<String[]>> sheetMap = ExcelUtil.readExcelFile(file);
        sheetMap.forEach((name, values) -> {
            if (values == null || values.size() <= 4) {

            } else {
                String fileName = file.getName();
                String pkg = fileName.substring(0, fileName.indexOf('.'));
                int index = name.indexOf(".");
                String className = name;
                if (index != -1)
                    className = name.substring(index + 1);
                values.remove(0);
                values.remove(0);
                String[] names = values.remove(0);
                values.remove(0);
                String clazzName = this.sampleConfig.samplePackage + "." + pkg + "." + className;
                try {
                    Class<Sample> clazz = (Class)Class.forName(clazzName);
                    List<Sample> samples = SampleReflectHelper.resolveSample(clazz, names, values);
                    Field field = clazz.getField("factory");
                    SampleFactory<Sample> factory = (SampleFactory)field.get(null);
                    factory.addSamples(samples);
                } catch (Exception e) {
                    this.log.warn("parse file error, file is {}", fileName, e);
                }
            }
        });
    }

    public void load(File file, boolean isNew) {
        try {
            this.log.info("on file change filename = {},isNew={}", file.getName(), Boolean.valueOf(isNew));
            loadSample(file);
        } catch (Exception e) {
            this.log.warn("on file change err,filename={},isNew={}", file.getName(), Boolean.valueOf(isNew));
        }
    }
}
